package com.qmock.pay.http;

import com.qmock.pay.exception.SignEncException;
import com.qmock.pay.runner.Bank;
import com.qmock.pay.runner.Service;
import com.qmock.pay.security.UmpayRSA;
import com.qmock.pay.umpay.UmpayStringUtils;
import com.qmock.pay.umpay.handler.UmpayHttpRequest;
import org.apache.log4j.Logger;
import org.webbitserver.HttpHandler;
import org.webbitserver.WebServer;
import org.webbitserver.WebServers;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * @author tianqing.wang
 */
public class PayMockServer {
    public Logger logger = Logger.getLogger(this.getClass());
    private String url;
    private int port;
    private Bank bank;
    private String serviceName;
    private WebServer webServer;
    private ExpectResponseInterface expectResponse;
    private UmpayHttpRequest httpRequest;
    private Service service;
    public PayMockServer(){
        this.port=9999;
    }
    public PayMockServer(int port){
        this.port=port;
    }
    public void start() throws ExecutionException, InterruptedException {
        if(this.url!=null){
            this.webServer=WebServers.createWebServer(this.port).add("/config",new ConfigHttpHandler()).add(this.url, getHandler()).start().get();
        }else{
            this.webServer= WebServers.createWebServer(this.port).add("/config",new ConfigHttpHandler()).add(getHandler()).start().get();
        }

    }

    public PayMockServer url(String url){
        this.url=url;
        try {
            logger.info("服务器运行URL->"+"http://"+ InetAddress.getLocalHost().getHostAddress().toString()+":"+this.port+url);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return this;
    }
    public void stop(){
        this.webServer.stop();
    }

    public PayMockServer mockBank(Bank bank,String serviceName){
        this.bank=bank;
        this.serviceName=serviceName;
        this.service=this.bank.bankService(this.serviceName);
        logger.info("服务器模拟了银行->"+bank.toString());
        logger.info("服务器模拟了服务->"+serviceName);
        return this;
    }

    public PayMockServer thenReturn(String responseXMLFile){
        DefaultXMLResponseParameters requsetParameters = new DefaultXMLResponseParameters(responseXMLFile);
        this.expectResponse=new ExpectResponse(requsetParameters.toPairs());
        logger.info("初始化了服务器端的响应参数...");
        for(Map.Entry<String,String> entry:requsetParameters.toPairs().getPairs().entrySet()){
            logger.info("初始化配置文件的响应参数--> key: "+entry.getKey()+", value: "+entry.getValue());
        }
        return this;
    }

    public PayMockServer thenReturn(ExpectResponseInterface expectResponseInterface){
        this.expectResponse=expectResponseInterface;
        return this;
    }

    public PayMockServer mockBank(Bank bank){
        this.bank=bank;
        logger.info("服务器模拟了银行->"+bank.toString());
        return this;
    }

    protected HttpHandler getHandler(){
            if(this.service!=null){
                return this.bank.handler(this.expectResponse,this.service,this.url);
            }else{
                return this.bank.handler(this.expectResponse,this.url);
            }
    }

    public ExpectResponseInterface getExpectResponseContent(){
        return this.expectResponse;
    }
    /**when的方式用于异步调用。指定了异步回调的响应参数来执行返回
     * @param  requestXML 请求xml的路径
     * @return  返回异步请求的响应。
     * */
    public AsynMockServer when(String requestXML) throws SignEncException {
        if(!new File(requestXML).exists()){
            throw new RuntimeException("制定的文件没有找到，请重新查看xml文件路径");
        }
        DefaultXMLRequsetParameters defaultXMLRequsetParameters=new DefaultXMLRequsetParameters(requestXML);
        ParameterPairs parameterPairs=defaultXMLRequsetParameters.toPairs();
        Map<String,String> paramsMap=parameterPairs.getPairs();
        String signString = UmpayStringUtils.toSignString(paramsMap);
        paramsMap.put("sign",UmpayRSA.getInstance().sign(signString));
        printMap(paramsMap);
        AsynHttpMockServer asynHttpMockServer=new AsynHttpMockServer(paramsMap);
        return asynHttpMockServer;
    }
	public UmpayHttpRequest getHttpRequest() {
		return httpRequest;
	}
	public void setHttpRequest(UmpayHttpRequest httpRequest) {
		this.httpRequest = httpRequest;
	}

    public WebServer server(){
        return this.webServer;
    }

    public void syncResponse(){
        this.expectResponse=InfoMap.getExpectResponse("info");
    }

    private void printMap(Map<String,String> map){
        if(map.size()==0)
            logger.warn("异步请求的参数没有添加成功，请检查配置文件..");
        for(Map.Entry<String,String> entry:map.entrySet()){
            logger.info("异步请求的参数-->"+" key: "+entry.getKey()+", value: "+entry.getValue());
        }
    }
}
